home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-01-22 | 27.1 KB | 1,062 lines |
-
- SimpleRexx: A Simple ARexx Interface
-
- by Michael Sinz
-
- The ability to handle scripts is a powerful feature for any
- application. Whenever users have a repetitive, well-defined job to do
- with application software, script capabilities allow them to perform
- the job automatically without any user intervention. For example,
- many communication programs allow the user to set up a script which
- will automatically dial up a host system, login to it, and check for
- messages to download. To encourage the development of more
- applications which have this powerful feature, Commodore has added
- ARexx to V2.0 of the Amiga system software.
-
-
-
- What Is ARexx?
-
- ARexx is the Amiga implementation of the REXX language. Like BASIC,
- ARexx is an interpreted language. ARexx can be used alone for almost
- any programming job, but the real power of ARexx is unleashed when it
- is used with applications as a system-level scripting language. With
- the addition of its own ARexx port and a small amount of code, an
- application can gain all the power scripting capabilities offer.
- There are other benefits as well. The burden of writing code to
- handle scripts is reduced significantly. Also, ARexx helps provide a
- consistent interface to the user. Without it, every developer who
- implements scripts must invent their own scripting language, forcing
- the user to learn several different scripting languages rather than
- just one.
-
- Perhaps best of all is that applications which support ARexx can
- "talk" to each other by sending commands and sharing data - even if
- they are from different vendors. For instance, a communications
- program with an ARexx port could be set up to automatically download
- data from a financial bulletin board and then pass the data to a
- spreadsheet application to create a graph or financial model. The
- ability of applications to "talk" to one another on a multitasking
- computer is known as Inter-process Communication (IPC).
-
- Because it interprets scripts and passes strings, ARexx has been
- optimized for string processing. Almost all ARexx interactions
- involve passing a string; numbers are even passed as ASCII
- representations in most situations.
-
- ARexx has enhanced abilities to send and receive control messages to
- and from many sources. An application that supports ARexx can send
- and receive these control messages. The messages contain text strings
- that are either interpreted directly by ARexx itself or that are
- passed on as commands to be processed by the destination application.
-
- ARexx also supplies methods for applications to send and recieve data
- through an ARexx port. The data can be sent in a message or via the
- ARexx RVI (Rexx Variable Interface). In either case, data can be
- transferred to and from ARexx. A complete ARexx supporting
- application would need to be able to send data to a requesting ARexx
- program/script and get data from that program.
-
-
-
- The SimpleRexx Routines
-
- Adding an ARexx interface to an application can be difficult,
- especially when working with it for the first time. SimpleRexx was
- written to serve not only as an example of how to implement an ARexx
- interface but also as a "wrapper" to be incorporated into other code.
- It contains routines to take care of the lower level ARexx work. It
- can be used to add minimal ARexx support to many applications in a
- backwards-compatible fashion. In other words, an application that
- uses SimpleRexx will still work on systems without ARexx (but won't be
- able to execute ARexx scripts).
-
- The code below consists of SimpleRexx.c, the "wrapper" code that makes
- up the ARexx interface, and an example, SimpleRexxExample.c, which
- illustrates the use of the wrapper. The test.rexx script is an
- example ARexx script to execute while SimpleRexxExample is running.
- It will send commands to SimpleRexxExample in order to control it.
- The test.results file shows the output of test.rexx.
-
- In addition to the code examples listed here, you will need to install
- the rexxsyslib.library and rexxsupport.library in the libs: directory
- of the target machine. Don't forget to give the rexxmast command
- either in your startup-sequence or from the CLI in order to start
- ARexx.
-
-
-
- Overview of Functions
-
- The source to SimpleRexx is a single file, SimpleRexx.c. The header
- file, SimpleRexx.h, contains the type definitions and prototypes for
- the functions.
-
- The SimpleRexx functions are used as follows:
-
- rexx_context=InitARexx(AppBaseName, Extension)
-
- This allocates and initializes a SimpleRexx ARexxContext
- structure. This context is much like a file handle in
- that it will be used in all other calls that make use of
- this SimpleRexx context. Since all SimpleRexx calls
- correctly check the rexx_context before doing work,
- you do not need to check the return result of this call.
- If ARexx is not available on your system, SimpleRexx
- won't do anything.
-
-
- port_name=ARexxName(rexx_context)
-
- This function returns a pointer to the name of the ARexx
- port's context. The name is based on the AppBaseName
- plus an invocation number allowing multiple copies of an
- application to run at the same time. If you have no
- ARexx port, it returns NULL.
-
-
- sigmask=ARexxSignal(rexx_context)
-
- This function returns the signal bit mask of your
- context's ARexx port. This should be combined with
- other signal masks to produce the argument to the Wait()
- call. This returns NULL if there is no signal mask.
-
- rmsg=GetARexxMsg(rexx_context)
-
- This function returns the next ARexx message that is
- waiting. rmsg=NULL if there is no message or ARexx is
- not around. rmsg=REXX_RETURN_ERROR if a message sent to
- ARexx via SendARexxMsg() returns an error.
-
- ReplyARexxMsg(rexx_context, rmsg, result, error)
-
- This function sends back the ARexx message received via
- GetARexxMsg(). The result field is a pointer to a
- result string that is returned via OPTIONS RESULTS in
- the RESULT ARexx variable. If you have no result, set
- this to NULL. Error is the error severity level. If
- this is 0, the result string will be returned. If this
- is non-zero, the error level will be returned in RC.
-
- worked=SendARexxMsg(rexx_context, string, StringFileFlag)
-
- This function sends a string to ARexx. It sets the
- default host to the context and sets the RXFB_STRING bit
- in the message if the StringFileFlag is set. This
- routine returns FALSE if the message was not sent.
-
- worked=SetARexxLastError(rexx_context, rmsg, ErrorString)
-
- This function uses the RVI (Rexx Variable Interface) to
- set a variable named <AppBaseName>.LASTERROR to the
- ErrorString. This is where the error message should go
- if there is an error. This function returns FALSE if
- this fails. You must call this routine after a
- GetARexxMsg() and before ReplyARexxMsg().
-
- FreeARexx(rexx_context)
-
- This closes a SimpleRexx context received from InitARexx().
-
-
-
- The Future of ARexx
-
- ARexx is much more than a system-level scripting language. Among
- other things, ARexx can be used like glue to put together a set of
- application modules. This frees the programmer from worrying about
- data sharing between modules so that more effort can be put into
- refining the code modules themselves. It also allows a user who
- understands ARexx to add their own refinements creating a truly custom
- environment. This customizability is also ideal for VARs or dealers
- who want to sell vertical market solutions.
-
-
-
- #
- # MakeFile for SimpleRexx and SimpleRexxExample
- #
-
- CFLAGS= -b1 -cfist -d0 -ms0 -rr1 -v -w
-
- HEAD= SimpleRexx.h
-
- CODE= SimpleRexx.c SimpleRexxExample.c
-
- OBJS= SimpleRexx.o SimpleRexxExample.o
-
- LIBS= LIB:lcsr.lib rexxvars.o LIB:amiga.lib
-
- .c.o:
- @LC $(CFLAGS) $*
-
- SimpleRexxExample: $(OBJS) $(LIBS)
- BLink FROM LIB:c.o $(OBJS) TO SimpleRexxExample LIB $(LIBS) SD SC ND
-
- SimpleRexx.o: SimpleRexx.c SimpleRexx.h
-
- SimpleRexxExample.o: SimpleRexxExample.c SimpleRexx.h
-
-
-
- /*
- * file: simplerexx.h
- *
- * Simple ARexx interface...
- *
- * This is a very "Simple" interface...
- */
-
- #ifndef SIMPLE_REXX_H
- #define SIMPLE_REXX_H
-
- #include <exec/types.h>
- #include <exec/nodes.h>
- #include <exec/lists.h>
- #include <exec/ports.h>
-
- #include <rexx/storage.h>
- #include <rexx/rxslib.h>
-
- /*
- * This is the handle that SimpleRexx will give you
- * when you initialize an ARexx port...
- *
- * The conditional below is used to skip this if we have
- * defined it earlier...
- */
- #ifndef AREXXCONTEXT
-
- typedef void *AREXXCONTEXT;
-
- #endif /* AREXXCONTEXT */
-
- /*
- * The value of RexxMsg (from GetARexxMsg) if there was an error returned
- */
- #define REXX_RETURN_ERROR ((struct RexxMsg *)-1L)
-
- /*
- * This function closes down the ARexx context that was opened
- * with InitARexx...
- */
- void FreeARexx(AREXXCONTEXT);
-
- /*
- * This routine initializes an ARexx port for your process
- * This should only be done once per process. You must call it
- * with a valid application name and you must use the handle it
- * returns in all other calls...
- *
- * NOTE: The AppName should not have spaces in it...
- * Example AppNames: "MyWord" or "FastCalc" etc...
- * The name *MUST* be less that 16 characters...
- * If it is not, it will be trimmed...
- * The name will also be UPPER-CASED...
- *
- * NOTE: The Default file name extension, if NULL will be
- * "rexx" (the "." is automatic)
- */
- AREXXCONTEXT InitARexx(char *,char *);
-
- /*
- * This function returns the port name of your ARexx port.
- * It will return NULL if there is no ARexx port...
- *
- * This string is *READ ONLY* You *MUST NOT* modify it...
- */
- char *ARexxName(AREXXCONTEXT);
-
- /*
- * This function returns the signal mask that the Rexx port is
- * using. It returns NULL if there is no signal...
- *
- * Use this signal bit in your Wait() loop...
- */
- ULONG ARexxSignal(AREXXCONTEXT);
-
- /*
- * This function returns a structure that contains the commands sent from
- * ARexx... You will need to parse it and return the structure back
- * so that the memory can be freed...
- *
- * This returns NULL if there was no message...
- */
- struct RexxMsg *GetARexxMsg(AREXXCONTEXT);
-
- /*
- * Use this to return a ARexx message...
- *
- * If you wish to return something, it must be in the RString.
- * If you wish to return an Error, it must be in the Error.
- */
- void ReplyARexxMsg(AREXXCONTEXT,struct RexxMsg *,char *,LONG);
-
- /*
- * This function will send a string to ARexx...
- *
- * The default host port will be that of your task...
- *
- * If you set StringFile to TRUE, it will set that bit for the message...
- *
- * Returns TRUE if it send the message, FALSE if it did not...
- */
- short SendARexxMsg(AREXXCONTEXT,char *,short);
-
- /*
- * This function will set an error string for the ARexx
- * application in the variable defined as <appname>.LASTERROR
- *
- * Note that this can only happen if there is an ARexx message...
- *
- * This returns TRUE if it worked, FALSE if it did not...
- */
- short SetARexxLastError(AREXXCONTEXT,struct RexxMsg *,char *);
-
- #endif /* SIMPLE_REXX_H */
-
-
-
- /*
- * File: SimpleRexx.c
- *
- * Simple ARexx interface...
- *
- * This is a very "Simple" interface to the world of ARexx...
- * For more complex interfaces into ARexx, it is best that you
- * understand the functions that are provided by ARexx.
- * In many cases they are more powerful than what is presented
- * here.
- *
- * This code is fully re-entrant and self-contained other than
- * the use of SysBase/AbsExecBase and the ARexx RVI support
- * library which is also self-contained...
- */
-
- #include <exec/types.h>
- #include <exec/nodes.h>
- #include <exec/lists.h>
- #include <exec/ports.h>
- #include <exec/memory.h>
-
- #include <proto/exec.h>
-
- #include <rexx/storage.h>
- #include <rexx/rxslib.h>
-
- #include <string.h>
- #include <ctype.h>
-
- /*
- * The prototypes for the few ARexx functions we will call...
- */
- struct RexxMsg *CreateRexxMsg(struct MsgPort *,char *,char *);
- void *CreateArgstring(char *,long);
- void DeleteRexxMsg(struct RexxMsg *);
- void DeleteArgstring(char *);
- BOOL IsRexxMsg(struct Message *);
-
- /*
- * Pragmas for the above functions... (To make this all self-contained...)
- * If you use RexxGlue.o, this is not needed...
- *
- * These are for Lattice C 5.x (Note the use of RexxContext->RexxSysBase)
- */
- #pragma libcall RexxContext->RexxSysBase CreateRexxMsg 90 09803
- #pragma libcall RexxContext->RexxSysBase CreateArgstring 7E 0802
- #pragma libcall RexxContext->RexxSysBase DeleteRexxMsg 96 801
- #pragma libcall RexxContext->RexxSysBase DeleteArgstring 84 801
- #pragma libcall RexxContext->RexxSysBase IsRexxMsg A8 801
-
- /*
- * Prototypes for the RVI ARexx calls... (link with RexxVars.o)
- */
- __stdargs long CheckRexxMsg(struct RexxMsg *);
- __stdargs long GetRexxVar(struct RexxMsg *,char *,char **);
- __stdargs long SetRexxVar(struct RexxMsg *,char *,char *,long);
-
- /*
- * Now, we have made the pragmas needed, let's get to work...
- */
-
- /*
- * A structure for the ARexx handler context
- * This is *VERY* *PRIVATE* and should not be touched...
- */
- struct ARexxContext
- {
- struct MsgPort *ARexxPort; /* The port messages come in at... */
- struct Library *RexxSysBase; /* We will hide the library pointer here... */
- long Outstanding; /* The count of outstanding ARexx messages... */
- char PortName[24]; /* The port name goes here... */
- char ErrorName[28]; /* The name of the <base>.LASTERROR... */
- char Extension[8]; /* Default file name extension... */
- };
-
- #define AREXXCONTEXT struct ARexxContext *
-
- #include "SimpleRexx.h"
-
- /*
- * This function returns the port name of your ARexx port.
- * It will return NULL if there is no ARexx port...
- *
- * This string is *READ ONLY* You *MUST NOT* modify it...
- */
- char *ARexxName(AREXXCONTEXT RexxContext)
- {
- register char *tmp=NULL;
-
- if (RexxContext) tmp=RexxContext->PortName;
- return(tmp);
- }
-
- /*
- * This function returns the signal mask that the Rexx port is
- * using. It returns NULL if there is no signal...
- *
- * Use this signal bit in your Wait() loop...
- */
- ULONG ARexxSignal(AREXXCONTEXT RexxContext)
- {
- register ULONG tmp=NULL;
-
- if (RexxContext) tmp=1L << (RexxContext->ARexxPort->mp_SigBit);
- return(tmp);
- }
-
- /*
- * This function returns a structure that contains the commands sent from
- * ARexx... You will need to parse it and return the structure back
- * so that the memory can be freed...
- *
- * This returns NULL if there was no message...
- */
- struct RexxMsg *GetARexxMsg(AREXXCONTEXT RexxContext)
- {
- register struct RexxMsg *tmp=NULL;
- register short flag;
-
- if (RexxContext)
- if (tmp=(struct RexxMsg *)GetMsg(RexxContext->ARexxPort))
- {
- if (tmp->rm_Node.mn_Node.ln_Type==NT_REPLYMSG)
- {
- /*
- * If we had sent a command, it would come this way...
- *
- * Since we don't in this simple example, we just throw
- * away anything that looks "strange"
- */
- flag=FALSE;
- if (tmp->rm_Result1) flag=TRUE;
-
- /*
- * Free the arguments and the message...
- */
- DeleteArgstring(tmp->rm_Args[0]);
- DeleteRexxMsg(tmp);
- RexxContext->Outstanding-=1;
-
- /*
- * Return the error if there was one...
- */
- tmp=flag ? REXX_RETURN_ERROR : NULL;
- }
- }
- return(tmp);
- }
-
- /*
- * Use this to return a ARexx message...
- *
- * If you wish to return something, it must be in the RString.
- * If you wish to return an Error, it must be in the Error.
- * If there is an error, the RString is ignored.
- */
- void ReplyARexxMsg(AREXXCONTEXT RexxContext,struct RexxMsg *rmsg,
- char *RString,LONG Error)
- {
- if (RexxContext) if (rmsg) if (rmsg!=REXX_RETURN_ERROR)
- {
- rmsg->rm_Result2=0;
- if (!(rmsg->rm_Result1=Error))
- {
- /*
- * if you did not have an error we return the string
- */
- if (rmsg->rm_Action & (1L << RXFB_RESULT)) if (RString)
- {
- rmsg->rm_Result2=(LONG)CreateArgstring(RString,
- (LONG)strlen(RString));
- }
- }
-
- /*
- * Reply the message to ARexx...
- */
- ReplyMsg((struct Message *)rmsg);
- }
- }
-
- /*
- * This function will set an error string for the ARexx
- * application in the variable defined as <appname>.LASTERROR
- *
- * Note that this can only happen if there is an ARexx message...
- *
- * This returns TRUE if it worked, FALSE if it did not...
- */
- short SetARexxLastError(AREXXCONTEXT RexxContext,struct RexxMsg *rmsg,
- char *ErrorString)
- {
- register short OkFlag=FALSE;
-
- if (RexxContext) if (rmsg) if (CheckRexxMsg(rmsg))
- {
- /*
- * Note that SetRexxVar() has more than just a TRUE/FALSE
- * return code, but for this "basic" case, we just care if
- * it works or not.
- */
- if (!SetRexxVar(rmsg,RexxContext->ErrorName,ErrorString,
- (long)strlen(ErrorString)))
- {
- OkFlag=TRUE;
- }
- }
- return(OkFlag);
- }
-
- /*
- * This function will send a string to ARexx...
- *
- * The default host port will be that of your task...
- *
- * If you set StringFile to TRUE, it will set that bit for the message...
- *
- * Returns TRUE if it send the message, FALSE if it did not...
- */
- short SendARexxMsg(AREXXCONTEXT RexxContext,char *RString,
- short StringFile)
- {
- register struct MsgPort *RexxPort;
- register struct RexxMsg *rmsg;
- register short flag=FALSE;
-
- if (RexxContext) if (RString)
- {
- if (rmsg=CreateRexxMsg(RexxContext->ARexxPort,
- RexxContext->Extension,
- RexxContext->PortName))
- {
- rmsg->rm_Action=RXCOMM | (StringFile ?
- (1L << RXFB_STRING):0);
- if (rmsg->rm_Args[0]=CreateArgstring(RString,
- (LONG)strlen(RString)))
- {
- /*
- * We need to find the RexxPort and this needs
- * to be done in a Forbid()
- */
- Forbid();
- if (RexxPort=FindPort(RXSDIR))
- {
- /*
- * We found the port, so put the
- * message to ARexx...
- */
- PutMsg(RexxPort,(struct Message *)rmsg);
- RexxContext->Outstanding+=1;
- flag=TRUE;
- }
- else
- {
- /*
- * No port, so clean up...
- */
- DeleteArgstring(rmsg->rm_Args[0]);
- DeleteRexxMsg(rmsg);
- }
- Permit();
- }
- else DeleteRexxMsg(rmsg);
- }
- }
- return(flag);
- }
-
- /*
- * This function closes down the ARexx context that was opened
- * with InitARexx...
- */
- void FreeARexx(AREXXCONTEXT RexxContext)
- {
- register struct RexxMsg *rmsg;
-
- if (RexxContext)
- {
- /*
- * Clear port name so it can't be found...
- */
- RexxContext->PortName[0]='\0';
-
- /*
- * Clean out any outstanding messages we had sent out...
- */
- while (RexxContext->Outstanding)
- {
- WaitPort(RexxContext->ARexxPort);
- while (rmsg=GetARexxMsg(RexxContext))
- {
- if (rmsg!=REXX_RETURN_ERROR)
- {
- /*
- * Any messages that come now are blown
- * away...
- */
- SetARexxLastError(RexxContext,rmsg,
- "99: Port Closed!");
- ReplyARexxMsg(RexxContext,rmsg,
- NULL,100);
- }
- }
- }
-
- /*
- * Clean up the port and delete it...
- */
- if (RexxContext->ARexxPort)
- {
- while (rmsg=GetARexxMsg(RexxContext))
- {
- /*
- * Any messages that still are coming in are
- * "dead" We just set the LASTERROR and
- * reply an error of 100...
- */
- SetARexxLastError(RexxContext,rmsg,
- "99: Port Closed!");
- ReplyARexxMsg(RexxContext,rmsg,NULL,100);
- }
- DeletePort(RexxContext->ARexxPort);
- }
-
- /*
- * Make sure we close the library...
- */
- if (RexxContext->RexxSysBase)
- {
- CloseLibrary(RexxContext->RexxSysBase);
- }
-
- /*
- * Free the memory of the RexxContext
- */
- FreeMem(RexxContext,sizeof(struct ARexxContext));
- }
- }
-
- /*
- * This routine initializes an ARexx port for your process
- * This should only be done once per process. You must call it
- * with a valid application name and you must use the handle it
- * returns in all other calls...
- *
- * NOTE: The AppName should not have spaces in it...
- * Example AppNames: "MyWord" or "FastCalc" etc...
- * The name *MUST* be less that 16 characters...
- * If it is not, it will be trimmed...
- * The name will also be UPPER-CASED...
- *
- * NOTE: The Default file name extension, if NULL will be
- * "rexx" (the "." is automatic)
- */
- AREXXCONTEXT InitARexx(char *AppName,char *Extension)
- {
- register AREXXCONTEXT RexxContext=NULL;
- register short loop;
- register short count;
- register char *tmp;
-
- if (RexxContext=AllocMem(sizeof(struct ARexxContext),
- MEMF_PUBLIC|MEMF_CLEAR))
- {
- if (RexxContext->RexxSysBase=OpenLibrary("rexxsyslib.library",
- NULL))
- {
- /*
- * Set up the extension...
- */
- if (!Extension) Extension="rexx";
- tmp=RexxContext->Extension;
- for (loop=0;(loop<7)&&(Extension[loop]);loop++)
- {
- *tmp++=Extension[loop];
- }
- *tmp='\0';
-
- /*
- * Set up a port name...
- */
- tmp=RexxContext->PortName;
- for (loop=0;(loop<16)&&(AppName[loop]);loop++)
- {
- *tmp++=toupper(AppName[loop]);
- }
- *tmp='\0';
-
- /*
- * Set up the last error RVI name...
- *
- * This is <appname>.LASTERROR
- */
- strcpy(RexxContext->ErrorName,RexxContext->PortName);
- strcat(RexxContext->ErrorName,".LASTERROR");
-
- /* We need to make a unique port name... */
- Forbid();
- for (count=1,RexxContext->ARexxPort=(VOID *)1;
- RexxContext->ARexxPort;count++)
- {
- stci_d(tmp,count);
- RexxContext->ARexxPort=
- FindPort(RexxContext->PortName);
- }
-
- RexxContext->ARexxPort=CreatePort(
- RexxContext->PortName,NULL);
- Permit();
- }
-
- if ( (!(RexxContext->RexxSysBase))
- || (!(RexxContext->ARexxPort)) )
- {
- FreeARexx(RexxContext);
- RexxContext=NULL;
- }
- }
- return(RexxContext);
- }
-
-
-
-
- /*
- * File: SimpleRexxExample.c
- *
- * This is an example of how to use the SimpleRexx code.
- */
-
- #include <exec/types.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <intuition/intuition.h>
-
- #include <proto/exec.h>
- #include <proto/intuition.h>
-
- #include <rexx/storage.h>
- #include <rexx/rxslib.h>
-
- #include <stdio.h>
- #include <string.h>
-
- #include "SimpleRexx.h"
-
- /*
- * Lattice control-c stop...
- */
- int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */
- int chkabort(void) { return(0); } /* really */
-
- /*
- * The strings in this program
- */
- char *strings[]=
- {
- "50: Window already open", /* STR_ID_WINDOW_OPEN */
- "101: Window did not open", /* STR_ID_WINDOW_ERROR */
- "50: No Window", /* STR_ID_WINDOW_NONE */
- "80: Argument error to WINDOW command", /* STR_ID_WINDOW_ARG */
- "100: Unknown command", /* STR_ID_COMMAND_ERROR */
- "ARexx port name: %s\n", /* STR_ID_PORT_NAME */
- "No ARexx on this system.\n", /* STR_ID_NO_AREXX */
- "SimpleRexxExample Window" /* STR_ID_WINDOW_TITLE */
- };
-
- #define STR_ID_WINDOW_OPEN 0
- #define STR_ID_WINDOW_ERROR 1
- #define STR_ID_WINDOW_NONE 2
- #define STR_ID_WINDOW_ARG 3
- #define STR_ID_COMMAND_ERROR 4
- #define STR_ID_PORT_NAME 5
- #define STR_ID_NO_AREXX 6
- #define STR_ID_WINDOW_TITLE 7
-
- /*
- * NewWindow structure...
- */
- static struct NewWindow nw=
- {
- 97,47,299,44,-1,-1,
- CLOSEWINDOW,
- WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|SIMPLE_REFRESH|NOCAREREFRESH,
- NULL,NULL,
- NULL,
- NULL,NULL,290,40,-1,-1,WBENCHSCREEN
- };
-
- /*
- * A *VERY* simple and simple-minded example of using the SimpleRexx.c code.
- *
- * This program, when run, will print out the name of the ARexx port it
- * opens. Use that port to tell it to SHOW the window. You can also
- * use the ARexx port to HIDE the window, to READTITLE the window's
- * titlebar, and QUIT the program. You can also quit the program by
- * pressing the close gadget in the window while the window is up.
- *
- * Note: You will want to RUN this program or have another shell available such
- * that you can still have access to ARexx...
- */
- void main(int argc,char *argv[])
- {
- short loopflag=TRUE;
- AREXXCONTEXT RexxStuff;
- struct Window *win=NULL;
- ULONG signals;
-
- if (IntuitionBase=(struct IntuitionBase *)
- OpenLibrary("intuition.library",NULL))
- {
- /*
- * Note that SimpleRexx is set up such that you do not
- * need to check for an error to initialize your REXX port
- * This is so your application could run without REXX...
- */
- RexxStuff=InitARexx("Example","test");
-
- if (argc)
- {
- if (RexxStuff) printf(strings[STR_ID_PORT_NAME],
- ARexxName(RexxStuff));
- else printf(strings[STR_ID_NO_AREXX]);
- }
-
- while (loopflag)
- {
- signals=ARexxSignal(RexxStuff);
- if (win) signals|=(1L << (win->UserPort->mp_SigBit));
-
- if (signals)
- {
- struct RexxMsg *rmsg;
- struct IntuiMessage *msg;
-
- signals=Wait(signals);
-
- /*
- * Process the ARexx messages...
- */
- while (rmsg=GetARexxMsg(RexxStuff))
- {
- char cBuf[24];
- char *nextchar;
- char *error=NULL;
- char *result=NULL;
- long errlevel=0;
-
- nextchar=stptok(ARG0(rmsg),
- cBuf,24," ,");
- if (*nextchar) nextchar++;
-
- if (!stricmp("WINDOW",cBuf))
- {
- if (!stricmp("OPEN",nextchar))
- {
- if (win)
- {
- error=strings[STR_ID_WINDOW_OPEN];
- errlevel=5;
- }
- else
- {
- nw.Title=strings[STR_ID_WINDOW_TITLE];
- if (!(win=OpenWindow(&nw)))
- {
- error=strings[STR_ID_WINDOW_ERROR];
- errlevel=30;
- }
- }
- }
- else if (!stricmp("CLOSE",nextchar))
- {
- if (win)
- {
- CloseWindow(win);
- win=NULL;
- }
- else
- {
- error=strings[STR_ID_WINDOW_NONE];
- errlevel=5;
- }
- }
- else
- {
- error=strings[STR_ID_WINDOW_ARG];
- errlevel=20;
- }
- }
- else if (!stricmp("READTITLE",cBuf))
- {
- if (win)
- {
- result=win->Title;
- }
- else
- {
- error=strings[STR_ID_WINDOW_NONE];
- errlevel=5;
- }
- }
- else if (!stricmp("QUIT",cBuf))
- {
- loopflag=FALSE;
- }
- else
- {
- error=strings[STR_ID_COMMAND_ERROR];
- errlevel=20;
- }
-
- if (error)
- {
- SetARexxLastError(RexxStuff,rmsg,error);
- }
- ReplyARexxMsg(RexxStuff,rmsg,result,errlevel);
- }
-
- /*
- * If we have a window, process those messages
- */
- if (win) while (msg=(struct IntuiMessage *)
- GetMsg(win->UserPort))
- {
- if (msg->Class==CLOSEWINDOW)
- {
- /*
- * Quit if the close gadget...
- */
- loopflag=FALSE;
- }
- ReplyMsg((struct Message *)msg);
- }
- }
- else loopflag=FALSE;
- }
- if (win) CloseWindow(win);
-
- FreeARexx(RexxStuff);
- CloseLibrary((struct Library *)IntuitionBase);
- }
- }
-
-
-
- /*
- * File: test.rexx
- *
- * SimpleRexx test...
- *
- * You need to run the SimpleRexxExample first...
- */
-
- Options FailAt 100
-
- Options Results
-
- /*
- * Try to read the window title bar
- */
- Address EXAMPLE1 ReadTitle
-
- if rc > 0 then say 'Error was 'EXAMPLE.LASTERROR
- else say 'Window title is 'Result
-
- /*
- * Bad WINDOW command...
- */
- Address EXAMPLE1 "Window Display"
-
- if rc > 0 then say 'Error was 'EXAMPLE.LASTERROR
- else say 'Window is now open'
-
- /*
- * Open the window
- */
- Address EXAMPLE1 "Window Open"
-
- if rc > 0 then say 'Error was 'EXAMPLE.LASTERROR
- else say 'Window is now open'
-
- /*
- * Open the window
- */
- Address EXAMPLE1 "Window Open"
-
- if rc > 0 then say 'Error was 'EXAMPLE.LASTERROR
- else say 'Window is now open'
-
- /*
- * Try to read the window title bar
- */
- Address EXAMPLE1 ReadTitle
-
- if rc > 0 then say 'Error was 'EXAMPLE.LASTERROR
- else say 'Window title is 'Result
-
- /*
- * Hide the window
- */
- Address EXAMPLE1 "Window Close"
-
- if rc > 0 then say 'Error was 'EXAMPLE.LASTERROR
- else say 'Window is now closed'
-
- /*
- * Try to hide the window again
- */
- Address EXAMPLE1 "Window Close"
-
- if rc > 0 then say 'Error was 'EXAMPLE.LASTERROR
- else say 'Window is now closed'
-
- /*
- * Send a command that does not exist
- */
- Address EXAMPLE1 Junk
-
- if rc > 0 then say 'Error was 'EXAMPLE.LASTERROR
- else say 'The command worked!!!'
-
- /*
- * Quit the program...
- */
- Address EXAMPLE1 Quit
-
-
-
-
- File: test.results
-
- Error was 50: No Window
- Error was 80: Argument error to WINDOW command
- Window is now open
- Error was 50: Window already open
- Window title is SimpleRexxExample Window
- Window is now closed
- Error was 50: No Window
- Error was 100: Unknown command
-